package LiuYun

import spinal.core._
import spinal.lib._

class StageEx2 extends Component{
    val io = new Bundle{
        val ic    :PipeCtrl = slave (new PipeCtrl)
        val idat  :SDatEx2  = in    (new SDatEx2 )
        val oc    :PipeCtrl = master(new PipeCtrl)
        val odat  :SDatEx3  = out   (new SDatEx3 )
        val dexcpt:DExcept  = slave (new DExcept )
        val fw    :Forwarding = out (new Forwarding)
        val exbus :CoreCancel = in  (new CoreCancel)
        val addrtrans_ok :Bool = in(Bool())
        val pa  :UInt = in (LISA.PA)//difftest need
    }
    val cancel:Bool = io.exbus.cancel
    val data:SDatEx3 = new SDatEx3 assignedFrom io.idat
    val pipe = new StageBuffer[SDatEx3](data)
    pipe.update(io.ic,io.oc,cancel)
    io.odat := pipe.data
    val I = Instructions
    val op:UInt = io.idat.subcode
    val mul = new Area{
        val valid:Bool = io.idat.itype.is_mul
        val x:UInt = io.idat.mul_x
        val y:UInt = io.idat.mul_y
        val s:UInt = x + y
        val res:UInt = I.select(op,"mul",Map(
            "h" -> s(63 downto 32),
            "l" -> s(31 downto  0))
        )
        when(valid){
            data.value := res
        }
    }
    io.fw.valid := io.ic.valid
    io.fw.grwr  := data.grwr
    io.fw.dest  := data.dest
    io.fw.block := io.idat.itype.is_mem || io.idat.itype.is_div
    io.fw.value := data.value
    io.dexcpt.allow := pipe.maygo
    pipe.ready := io.addrtrans_ok//Mux((io.idat.itype.is_mem || io.idat.itype.is_cacop), io.addrtrans_ok, True)
    pipe.newex := io.dexcpt.ex
    data.esubc := U(0)
    when(!io.ic.ex){
        when(io.dexcpt.ex){
            assert(io.idat.itype.is_mem || io.idat.itype.is_cacop)
            data.ecode := io.dexcpt.ecode
            data.esubc := io.dexcpt.esubc
        }
    }

    data.pa := io.pa //difftest
}
